/**
 * 
 */
package roborally.model.items;

import be.kuleuven.cs.som.annotate.*;
import be.kuleuven.cs.som.taglet.*;
import roborally.model.*;
import roborally.model.Energy.Unit;
import be.kuleuven.cs.som.annotate.*;
import be.kuleuven.cs.som.taglet.*;

/**
 * A class of repair kits. When a robot uses a repair kit, the energy stored in the kit is used
 * to increase the maximum amount of energy the robot can have, thus repairing any damage the
 * robot may have taken from laser shots. The robot's maximum energy increases by 1 Ws for every
 * 2 Ws stored in the kit.
 * @author Mathieu REYMOND
 * @author Joren VERSPEURT
 *
 */
public class RepairKit extends Item {

	/**
	 * Make a new repair kit with a given weight and amount of energy.
	 * 
	 * @param weight The new repair kit's weight.
	 * @param energy The new repair kit's energy in Ws.
	 */
	public RepairKit(int weight, double energy) {
		super(weight);
		setEnergy(new Energy(energy));
	}
	
	/**
	 * Return the amount of energy this repair kit currently holds.
	 * @return The amount of energy this repair kit currently holds
	 */
	@Basic @Raw
	public Energy getEnergy() {
		return this.energy;
	}
	
	/**
	 * Set the energy to a new amount of energy.
	 * @param newEnergy The amount of energy to set.
	 */
	@Model @Basic
	private void setEnergy(Energy newEnergy) {
		this.energy = newEnergy;
	}
	
	/**
	 * Recharge the repair kit by the given amount.
	 * 
	 * @param amount The amount of energy that will be added to the repair kit
	 * @effect setEnergy(getEnergy()+amount)
	 */
	public void recharge(Energy amount) {
		setEnergy(new Energy(getEnergy().getValueIn(Energy.Unit.WS)+amount.getValueIn(Energy.Unit.WS)));
	}
	
	/**
	 * The amount of energy this repairkit is currently holding
	 */
	private Energy energy;

	/**
	 * The amount of energy that is added to this repair kit's stored energy when it is hit by a laser.
	 */
	@Basic @Immutable
	public Energy getLaserCharge() {
		return LASER_CHARGE;
	}

	/**
	 * The amount of energy that is added to this repair kit's stored energy when it is hit by a laser.
	 */
	private static final Energy LASER_CHARGE = new Energy(500);

	/**
	 * Invoked when a robot uses this repair kit. Increases the robot's maximum energy.
	 * 
	 * @param robot The robot that will use this repair kit.
	 * @effect ...
	 * 		   | if robot.getMaxEnergy()+(this.getEnergy()/2) > 20000
	 * 		   | then robot.recharge(20000-robot.getMaxEnergy())
	 * 		   | else robot.recharge(this.getEnergy()/2);
	 */
	@Override
	public void use(Robot robot) {
		if(robot.getCurrentMaxEnergy().getValueIn(Energy.Unit.WS)+(this.getEnergy().getValueIn(Energy.Unit.WS)/2) > robot.getMaxEnergy().getValueIn(Energy.Unit.WS)){
			robot.repair(new Energy(robot.getMaxEnergy().getValueIn(Energy.Unit.WS)-robot.getCurrentMaxEnergy().getValueIn(Energy.Unit.WS)));
			this.setEnergy(new Energy(getEnergy().getValueIn(Unit.WS) - 2*(robot.getMaxEnergy().getValueIn(Energy.Unit.WS)-robot.getCurrentMaxEnergy().getValueIn(Energy.Unit.WS))));
		}
		else{
			robot.repair(new Energy(this.getEnergy().getValueIn(Energy.Unit.WS)/2));
			this.setEnergy(new Energy(0));
		}
	}
	
	/**
	 * This method is invoked when a repair kit is hit by a laser.
	 * 
	 * @effect ...
	 * 		   | recharge(getLaserCharge())
	 */
	@Override
	public void takeShot() {
		recharge(getLaserCharge());
	}
	
	/**
	 * Clone this repair kit.
	 * 
	 * @return ...
	 * 		   | (result.getBoard() == this.getBoard() && result.getPosition() == this.getPosition())
	 * @return ...
	 * 		   | result.equals(this(getWeight(), getEnergy())
	 */
	@Override
	public RepairKit clone() {
		RepairKit clone = new RepairKit(getWeight(), getEnergy().getValueIn(Energy.Unit.WS));
		clone.setBoardPosition(getBoard(), getPosition());
		return clone;
	}

	@Override
	public String toString(){
		return "RK"+getPosition()+" ("+getEnergy()+")";
	}

}
